package com.henry.base.concurrency;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.atomic.AtomicInteger;

public class AreaCalculus {
    public static class NodeArea extends RecursiveTask<Double> {
        private static final double THRESHOLD=0.001;
        private static final int SLIC_NUM=10;
        public static AtomicInteger counter = new AtomicInteger(0);

        private double startLoc;
        private double endLoc;

        public NodeArea(double startLoc, double endLoc) {
            this.startLoc = startLoc;
            this.endLoc = endLoc;
        }

        @Override
        protected Double compute() {
            double sum=0;
            boolean canCompute = (endLoc - startLoc) <= THRESHOLD;
            if (canCompute) {
                sum = calc(startLoc, endLoc);
//                counter.getAndIncrement();
//                System.out.println(counter + "--> calc result between " + (startLoc) + "--" + (endLoc));

            } else {
                double step = (endLoc - startLoc) / SLIC_NUM;
                for (int i = 0; i < SLIC_NUM; i++) {
                    NodeArea task = new NodeArea(startLoc + i * step, startLoc + (i + 1) * step);
                    task.fork();
                    sum+=task.join();
                }
            }
            return sum;
        }

        private double calc(double startLoc, double endLoc) {
            return (1/startLoc+1/endLoc)/2*(endLoc-startLoc);
        }
    }
    public static void main(String[] args){
        NodeArea nodeArea = new NodeArea(1, 100);
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        ForkJoinTask<Double> result = forkJoinPool.submit(nodeArea);
        long l = System.currentTimeMillis();
        try {
            System.out.println("Final Area:"+result.get());
            long l1 = System.currentTimeMillis();
            System.out.println("The whole process consumes "+(l1-l)+"ms");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}
